#pragma once
#include <initializer_list>
#include <memory>
#ifndef RAPIDJSON_HAS_CXX11_RVALUE_REFS
#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1
#define RAPIDJSON_HAS_STDSTRING 1 
#endif
#include "writer.h"
#include "type.h"
#include "tuple_index.h"

namespace rapidjson {

class StdStringOutputStream {
public:
    using Ch = char;
    StdStringOutputStream(std::string &_buf) : buf(_buf) {}
    StdStringOutputStream(const StdStringOutputStream &) = delete;
    StdStringOutputStream & operator=(const StdStringOutputStream &) = delete;
    StdStringOutputStream(StdStringOutputStream &&) = default;
    StdStringOutputStream & operator=(StdStringOutputStream &&) = default;
//以下为输入流需要实现的接口,此为输出流所以这些接口默认不予实现 
    Ch Peek() const { return '\0'; }
    Ch Take() { return '\0'; }
    std::size_t Tell() const { return 0; }
//以下为输出流需要实现的接口
    void Put(Ch c) { buf.push_back(c); }
    void Flush() {}
//以下为原位解析需要实现的接口,本序列化没有用到原位解析所以不予实现
    Ch* PutBegin() { return 0; }
    std::size_t PutEnd(Ch*) { return 0; }
 
private:
    std::string &buf;
};
//using BUFFER = StringBuffer;
//using BUFFER = BasicOStreamWrapper<std::ostringstream>;
//using BUFFER = StdStringOutputStream;
using StdStringWriter = Writer<StdStringOutputStream>;

template <typename T, typename WRITER>
class has_memberfunc_serialize  {
    typedef char _Has;
    typedef int _Hasnt;
    template<typename cls, void (cls::*)(WRITER &) const>
    struct fooMatcher;
    template <typename cls>
    static _Has hasFoo(fooMatcher<cls, &cls::serialize>*);
    template <typename cls>
    static _Hasnt hasFoo(...);
public:
    static constexpr bool value = (sizeof(hasFoo<T>(nullptr)) == sizeof(_Has));
};

template<typename WRITER>
struct Serializer {
    //针对unique_ptr的序列化
    template<typename T, typename D>
    static void serialize(WRITER &writer, const std::unique_ptr<T, D> &ptr) 
	{
		(ptr != nullptr) ? serialize(writer, *ptr) : (void)writer.Null();
	}
    //针对shared_ptr的序列化
    template<typename T>
    static void serialize(WRITER &writer, const std::shared_ptr<T> &ptr) 
	{
		(ptr != nullptr) ? serialize(writer, *ptr) : (void)writer.Null();
	}

    //针对char[]的序列化
	template<std::size_t N>
	static void serialize(WRITER &writer, const char (&arr)[N]) {writer.String(arr);}
    //针对string的序列化
    static void serialize(WRITER &writer, const std::string &str) {writer.String(str);}
    //针对bitset的序列化
	template<std::size_t N>
	static void serialize(WRITER &writer, const std::bitset<N> &bits) {(N <= 64) ? writer.Uint64(bits.to_ullong()) : writer.String(bits.to_string());}
    //针对bool的json序列化
    static void serialize(WRITER &writer, const bool &v) {writer.Bool(v);}
    //针对整数的json序列化
    template<typename T>
	static void serialize(WRITER &writer, const T &v, typename std::enable_if<std::is_same<char, T>::value
                                                                || std::is_same<uint8_t, T>::value
                                                                || std::is_same<short, T>::value
                                                                || std::is_same<uint16_t, T>::value
                                                                || std::is_enum<T>::value
                                                                || std::is_same<int, T>::value, int>::type = 0) {writer.Int((int)v);}
    static void serialize(WRITER &writer, const uint32_t &v) {writer.Uint(v);}
    static void serialize(WRITER &writer, const int64_t &v) {writer.Int64(v);}
    static void serialize(WRITER &writer, const uint64_t &v) {writer.Uint64(v);}
    static void serialize(WRITER &writer, const float &v) {writer.Double(v);}
    static void serialize(WRITER &writer, const double &v) {writer.Double(v);}
    //针对std容器包括vector、list、set、array的json序列化
	template<typename T>
	static void serialize(WRITER &writer, const T &t, typename std::enable_if<is_container<T>::value, int>::type = 0)
	{
		if (t.empty()) {
            //writer.Null(); //输出null
			writer.StartArray();
            writer.EndArray();  //输出[]
			return;
		}
        writer.StartArray();
        for (auto &it : t)
			serialize(writer, it);
        writer.EndArray();
	}
    //针对T[N]的json序列化
    template<typename T, std::size_t N>
    static void serialize(WRITER &writer, const T (&t)[N])
    {
        writer.StartArray();
        for (auto &it : t)
            serialize(writer, it);
        writer.EndArray();
    }
    //针对map<string,string>的序列化
    template<typename T>
    static void serialize(WRITER &writer, const T &t, typename std::enable_if<is_std_map<T>::value 
                                                                            && std::is_same<typename T::key_type, std::string>::value
                                                                            && std::is_same<typename T::mapped_type, std::string>::value, int>::type = 0)
    {
        writer.StartObject();
        for (auto &it : t) {
            writer.Key(it.first);
            writer.String(it.second);
        }
        writer.EndObject();
    }
    //针对map<integer,integer>的序列化
    template<typename T>
    static void serialize(WRITER &writer, const T &t, typename std::enable_if<is_std_map<T>::value 
                                                                            && std::is_integral<typename T::key_type>::value
                                                                            && std::is_integral<typename T::mapped_type>::value, int>::type = 0)
    {
        writer.StartObject();
        for (auto &it : t) {
            writer.Key(std::to_string(it.first));
            writer.Int64(it.second);
        }
        writer.EndObject();
    }
    //针对map<integer,integer>的序列化
    template<typename T>
    static void serialize(WRITER &writer, const T &t, typename std::enable_if<is_std_map<T>::value 
                                                                            && std::is_integral<typename T::key_type>::value
                                                                            && is_std_map<typename T::mapped_type>::value, int>::type = 0)
    {
        writer.StartObject();
        for (auto &it : t) {
            writer.Key(std::to_string(it.first));
            serialize(writer, it.second);
        }
        writer.EndObject();
    }
    //针对map<integer,class>的序列化
	template<typename T>
	static void serialize(WRITER &writer, const T &t, typename std::enable_if<is_std_map<T>::value 
                                                                                && std::is_integral<typename T::key_type>::value
                                                                                && is_json_class<typename T::mapped_type>::value, int>::type = 0)
	{
		//static_assert(is_json_class<T::mapped_type>::value, "the value of map must be struct or class!");
		if (t.empty()) {
            //writer.Null(); //输出null
			writer.StartArray();
            writer.EndArray();  //输出[]
			return;
		}
        writer.StartArray();
		for (auto &it : t) {
            writer.StartObject();
            writer.Key(MAP_KEY);
			serialize(writer, it.first);
			serialize(writer, it.second, true);
            writer.EndObject();
		}
        writer.EndArray();
	}
    //遍历类的Metas和Names分别对类中的成员json序列化
	template<int... Indexs, typename TP1, typename TP2>
	static void foreach_tuple(WRITER &writer, tuple_index<Indexs...> ids, TP1 && names, TP2 && metas)
	{
		std::initializer_list<int>{(writer.Key(std::get<Indexs>(names)), serialize(writer, std::get<Indexs>(metas)), 0)...};
	}
    //针对除去json基础类和std容器以及特定类型的json序列化
	template<typename T>
	static void serialize(WRITER &writer, const T &t, typename std::enable_if<is_json_class<T>::value && !has_memberfunc_serialize<T, WRITER>::value, bool>::type ready = false)
	{
        if (ready) {
            foreach_tuple(writer, typename make_tuple_index<T::element_size>::type(), t.Names(), t.Metas());
        } else {
            writer.StartObject();
            foreach_tuple(writer, typename make_tuple_index<T::element_size>::type(), t.Names(), t.Metas());
            writer.EndObject();
        }
	}
    //针对特定实现了serialize接口类的json序列化
    template<typename T>
    static void serialize(WRITER &writer, const T &t, typename std::enable_if<is_json_class<T>::value && has_memberfunc_serialize<T, WRITER>::value, bool>::type = false)
    {
        t.serialize(writer);
    }
};
//序列化函数接口
template<typename T, typename OutputStream>    //OutputStream的实现参考StdStringOutputStream
static inline void serialize(T && t, OutputStream &os)
{
    using WRITER = Writer<OutputStream>;
    WRITER writer(os);
    Serializer<WRITER>::serialize(writer, t);
}

template<typename T>
static inline void serialize(T && t, std::string &buf)
{
    using WRITER = Writer<StdStringOutputStream>;
    if (buf.empty()) {
        buf.resize(4096, '\0');//默认初始化4K用以存放json序列化结果
        buf.clear();
    }
    StdStringOutputStream os(buf);
    WRITER writer(os);
    Serializer<WRITER>::serialize(writer, t);
}

template<typename T>
static inline std::string serialize(T && t)
{
    using WRITER = Writer<StdStringOutputStream>;
    std::string buf(4096, 0);   //默认初始化4K用以存放json序列化结果
    buf.clear();
    StdStringOutputStream os(buf);
    WRITER writer(os);
    Serializer<WRITER>::serialize(writer, t);
    return std::move(buf);
}

} //end of namespace rapidjson
